package com.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.model.shared.model.VariableInstance;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.ReleaseTaskPayloadBuilder;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.model.payloads.ReleaseTaskPayload;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.*;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.io.FileUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.time.Instant;
import java.util.List;
import java.util.Map;

@Slf4j
@RequestMapping("/manage/")
@RestController
public class RequestVacationController {
    private final ProcessRuntime processRuntime;

    private final  TaskRuntime taskRuntime;
    private final  ObjectMapper objectMapper;
    private final TaskService taskService;
    private final ProcessEngineConfiguration processEngineConfiguration;
    private final HistoryService historyService;
    private final RuntimeService runtimeService;
    ProcessDiagramGenerator imageGenerator = new DefaultProcessDiagramGenerator();
    private final RepositoryService repositoryService;
private final ManagementService managementService;


    public RequestVacationController(ProcessRuntime processRuntime, TaskRuntime taskRuntime,TaskService taskService,ProcessEngineConfiguration processEngineConfiguration,HistoryService historyService,RuntimeService runtimeService,RepositoryService repositoryService,ManagementService managementService) {
        this.processRuntime = processRuntime;
        this.taskRuntime = taskRuntime;
         objectMapper = new ObjectMapper();
         this.taskService=taskService;
         this.processEngineConfiguration=processEngineConfiguration;
         this.historyService=historyService;
         this.runtimeService=runtimeService;
        this.repositoryService=repositoryService;
        this.managementService=managementService;

    }
    /**
     {
     "":"",
     put("employeeName", "john");
     put("numberOfDays", 3L);
     put("reason", "i need a break");
     put("startDate","11-01-2022 00:00");
     }
     */
    @RequestMapping(value = "vacationRequest")
    public String vacationRequest(@RequestBody Map<String,Object> map) {
        String reason = String.valueOf(map.get("reason"));
//     org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
        log.info("> Starting process to process content: " + map.values().toString() + " at " + Instant.now().toString());
        ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                .start()
                .withProcessDefinitionKey("demo-old")
                .withName("Processing Content: " + reason)
                .withVariables(map)
                .build());
        log.info(">>> Created Process Instance: " + processInstance);
        return "ops ok!!! ,";
    }

    /**
     {
         "vacationApproved": false,
         "comments": "have a deadline task"
     }
     */
    @RequestMapping(value = "dealWithVacationRequest")
    public String dealWithVacationRequest( @RequestBody Map<String, Object> map) throws IOException {
        Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
        if (tasks.getTotalItems() > 0) {
            for (Task t : tasks.getContent()) {

                log.info("> Claiming task: " + t.getId());
                try{
                    taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(t.getId()).build());
                }catch (Exception e){
                    e.printStackTrace();
                    ReleaseTaskPayload releaseTaskPayload = new ReleaseTaskPayload();
                    releaseTaskPayload.setTaskId(t.getId());
                    taskRuntime.release(releaseTaskPayload);
                }
                taskService.complete(t.getId(),map);
            }
        } else {
            log.info("> There are no task for me to work on.");
        }
        return "ops ok";
    }

    @RequestMapping("currentlyStatus")
    public void currentlyStatus(HttpServletResponse response) throws IOException {
        Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
        if (tasks.getTotalItems() > 0) {
            for (Task t : tasks.getContent()) {
                List<String> activityIds = runtimeService.getActiveActivityIds(t.getProcessInstanceId());
                InputStream diagram = imageGenerator
                        .generateDiagram(repositoryService.getBpmnModel(t.getProcessDefinitionId()), activityIds);

                response.addHeader("context-type", MediaType.APPLICATION_OCTET_STREAM_VALUE);
                response.addHeader("Content-Disposition","attachment; filename=\"fname.svg\"");
                ServletOutputStream outputStream = response.getOutputStream();
                outputStream.write(diagram.readAllBytes());
                outputStream.flush();
            }
        }
    }
}
